package com.corpgovernment.supplier.service;

import com.corpgovernment.api.supplier.soa.constant.ProductTypeEnum;
import com.corpgovernment.api.supplier.soa.response.GetSupplierInfoResponse;
import com.corpgovernment.api.supplier.vo.AtUserLoginVo;
import com.corpgovernment.api.supplier.vo.MbSupplierInfoVo;
import com.corpgovernment.common.base.AbstractBaseService;
import com.corpgovernment.common.base.Page;
import com.corpgovernment.common.common.CorpBusinessException;
import com.corpgovernment.common.enums.SiteEnum;
import com.corpgovernment.common.utils.PageUtils;
import com.corpgovernment.organization.constant.OrganizationResponseCodeEnum;
import com.corpgovernment.organization.operatelog.service.pojo.SupplierInfoPojo;
import com.corpgovernment.organization.util.StrUtils;
import com.corpgovernment.organization.vo.PageVo;
import com.corpgovernment.supplier.common.DefExample;
import com.corpgovernment.supplier.entity.db.AtUserLogin;
import com.corpgovernment.supplier.entity.db.MbSupplierExtendInfo;
import com.corpgovernment.supplier.entity.db.MbSupplierInfo;
import com.corpgovernment.supplier.entity.db.SupplierCompany;
import com.corpgovernment.supplier.mapper.MbSupplierExtendInfoMapper;
import com.corpgovernment.supplier.mapper.MbSupplierInfoMapper;
import com.corpgovernment.supplier.mapper.SupplierCompanyMapper;
import com.corpgovernment.supplier.vo.QuerySupplierListRequest;
import com.corpgovernment.supplier.vo.SupplierDataModelMapper;
import com.corpgovernment.supplier.vo.SupplierListInfo;
import com.ctrip.corp.obt.generic.utils.CollectionUtils;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import com.ctrip.corp.obt.shard.context.PageContext;
import com.ctrip.corp.obt.shard.sql.mybatis.interceptor.pagination.IPage;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class MbSupplierInfoService extends AbstractBaseService {

    @Autowired
    private MbSupplierInfoMapper siMapper;
    @Autowired
    private SupplierCompanyMapper supplierCompanyMapper;
    @Autowired
    private AtUserLoginService ulSrv;
    @Autowired
    private MbSupplierCompanyService scSrv;
    @Autowired
    private MbSupplierExtendInfoMapper seiMapper;
    @Autowired
    private SupplierDataModelMapper siDmm;
    @Autowired
    private MbSupplierExtendInfoMapper mbSupplierExtendInfoMapperl;

    /**
     * 模糊查询没被冻结并且此企业没有的供应商
     */
    public List<MbSupplierInfo> querySupplierListByNameOrCode(String nameOrCode, String excludeCorpId) {
        Example e = buildListExample(nameOrCode, null, false);
        List<MbSupplierInfo> mbSupplierInfos = siMapper.selectByExample(e);
        if (StringUtils.isNotBlank(excludeCorpId)) {
            Example example = new Example(SupplierCompany.class);
            example.createCriteria().andEqualTo("companyCode", excludeCorpId)
                    .andEqualTo("isDeleted", false);
            List<String> supplierCode = supplierCompanyMapper.selectByExample(example).stream()
                    .map(SupplierCompany::getSupplierCode)
                    .collect(Collectors.toList());
            mbSupplierInfos.removeIf(mbSupplierInfo -> supplierCode.contains(mbSupplierInfo.getSupplierCode()));
        }
        return mbSupplierInfos;
    }

    public List<MbSupplierInfo> listInSupplierCode(List<String> supplierCodeList) {
        Example e = new Example(MbSupplierInfo.class);
        e.createCriteria().andIn("supplierCode", supplierCodeList)
                .andEqualTo("isDeleted", false);
        return siMapper.selectByExample(e);
    }

    public Map<String, MbSupplierInfo> getSupplierInfoMap(List<String> supplierCodeList) {
        List<MbSupplierInfo> supplierInfoList = listInSupplierCode(supplierCodeList);
        if (CollectionUtils.isEmpty(supplierInfoList)){
            return Collections.emptyMap();
        }
        Map<String,MbSupplierInfo> supplierInfoMap = supplierInfoList.stream().collect(Collectors.toMap(MbSupplierInfo::getSupplierCode, Function.identity()));
        return supplierInfoMap;
    }
    public MbSupplierInfo loadBySupplierCode(String supplierCode) {
        Example e = new Example(MbSupplierInfo.class);
        e.createCriteria().andEqualTo("supplierCode", supplierCode)
                .andEqualTo("isDeleted", false);
        return siMapper.selectOneByExample(e);
    }

    public List<MbSupplierInfo> loadBySupplierCodes(List<String> supplierCodes) {
        Example e = new Example(MbSupplierInfo.class);
        e.createCriteria().andIn("supplierCode", supplierCodes)
                .andEqualTo("isDeleted", false);
        return siMapper.selectByExample(e);
    }

    public void froze(Long id) {
        MbSupplierInfo si = loadById(id);
	    if (si == null) {
		    throw new CorpBusinessException(OrganizationResponseCodeEnum.GET_SUPPLIER_INFO_NULL);
	    }
	    if (si.getIsFreeze()) {
		    return;
	    }
        String supplierCode = si.getSupplierCode();
        String s = scSrv.queryRelatedUsefulOrg(supplierCode);
        if (StringUtils.isNotBlank(s)) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.SUPPLIER_IN_USE_DONT_LOCK, s);
        }
        si = new MbSupplierInfo();
        si.setIsFreeze(true);
        si.setSupplierCode(supplierCode);
        updateBySupplierCode(si);
    }

    private MbSupplierInfo loadById(Long id) {
        return siMapper.selectByPrimaryKey(id);
    }

    public void unFroze(Long id) {
        MbSupplierInfo si = new MbSupplierInfo();
        si.setIsFreeze(false);
        si.setId(id);
        siMapper.updateByPrimaryKeySelective(si);
    }

    private void updateBySupplierCode(MbSupplierInfo record) {
	    if (StringUtils.isBlank(record.getSupplierCode())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.SUPPLIER_CODE_NULL);
	    }
        Example e = new Example(MbSupplierInfo.class);
        e.createCriteria().andEqualTo("supplierCode", record.getSupplierCode())
                .andEqualTo("isDeleted", false);
        siMapper.updateByExampleSelective(record, e);
    }

    /**
     * 获取供应商列表
     */
    public PageInfo<MbSupplierInfo> pageQuery(QuerySupplierListRequest req) {
        Example e = buildListExample(req.getNameOrId(), ProductTypeEnum.loadByName(req.getServiceType()), req.getIsFreeze());
        return PageHelper.startPage(req.getPageNum(), req.getPageSize())
                .doSelectPageInfo(() -> siMapper.selectByExample(e));
    }

    public SupplierInfoPojo convertPojo() {
        Example e = new Example(SupplierCompany.class);
        PageInfo<MbSupplierInfo> objectPageInfo = PageHelper.startPage(1, 5).doSelectPageInfo(() -> siMapper.selectByExample(e));
        SupplierInfoPojo supplierInfoPojo = null;
        if (objectPageInfo != null) {
            Page<SupplierListInfo> build = PageUtils.build(
                    objectPageInfo,
                    si -> {
                        SupplierListInfo sli = new SupplierListInfo();
                        BeanUtils.copyProperties(si, sli);
                        sli.setProducts(ProductTypeEnum.getProductList(si.getSupportProduct())
                                .stream().filter(p -> !ProductTypeEnum.intlflight.name().equals(p)).collect(Collectors.toList()));
                        return sli;
                    });
            if (build != null && !CollectionUtils.isEmpty(build.getList())) {
                SupplierListInfo supplierListInfo = build.getList().get(0);
                List<String> products = supplierListInfo.getProducts();
                List<String> get = Lists.newArrayList();
                if (!CollectionUtils.isEmpty(products)) {
                    for (String value : products) {
                        get.add(SiteEnum.get(value).getDesc());
                    }
                }
                supplierInfoPojo = JsonUtils.convert(supplierListInfo, SupplierInfoPojo.class);
                supplierInfoPojo.setProducts(StringUtils.join(get, ","));
            }
        }
        return supplierInfoPojo;
    }

    private Example buildListExample(String nameOrCode, ProductTypeEnum pt, Boolean isFreeze) {
        Example e = new DefExample(MbSupplierInfo.class);
        Example.Criteria c = e.createCriteria();
        if (StringUtils.isNotBlank(nameOrCode)) {
            c.andCondition(" (supplier_code like '%" + nameOrCode
                    + "%' or supplier_name like '%" + nameOrCode
                    + "%') ");
        }
        if (pt != null) {
            c.andCondition("support_product & " + pt.getId());
        }
        if (isFreeze != null) {
            c.andEqualTo("isFreeze", isFreeze);
        }
        return e;
    }

    public List<MbSupplierInfoVo> loadSupplierInfo(List<Long> ids, List<String> supplierCodes) {
        List<MbSupplierInfoVo> siVos = siMapper.loadSupplierInfoVos(ids, supplierCodes);
        List<String> excludes = Lists.newArrayList(ProductTypeEnum.i18n_flight.name(), ProductTypeEnum.other.name());
        siVos.forEach(si -> {
            si.setProduct(ProductTypeEnum.getProductList(si.getSupportProduct())
                    .stream().filter(p -> !excludes.contains(p)).collect(Collectors.toList()));
            si.setServerTypes(siDmm.loadSrvTypes(si.getServiceType()));
        });
        return siVos;
    }

    @Transactional(rollbackFor = Exception.class)
    public void insert(SupplierInfo si) {
        MbSupplierInfo baseInfo = si.getBasInfo();
        MbSupplierExtendInfo extendInfo = si.getExtendInfo();
        if (loadBySupplierCode(baseInfo.getSupplierCode()) != null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.SUPPLIER_CODE_CONFLICT);
        }
        seiMapper.insertSelective(extendInfo);
        siMapper.insertSelective(baseInfo);
        AtUserLogin ul = new AtUserLogin();
        BeanUtils.copyProperties(si.getAdminInfo(), ul);
		ul.setUserId(si.getAdminInfo().getUid());
        ul.setIsAdmin(true);
        ulSrv.insertOrUpdate(ul);
    }

    @Transactional(rollbackFor = Exception.class)
    public void update(SupplierInfo si) {
        MbSupplierInfo baseInfo = si.getBasInfo();
        MbSupplierExtendInfo extendInfo = si.getExtendInfo();
        baseInfo.setSupplierCode(null);
        siMapper.updateByPrimaryKeySelective(baseInfo);
        baseInfo = siMapper.selectByPrimaryKey(baseInfo.getId());
        Example e = new DefExample(MbSupplierExtendInfo.class);
        e.createCriteria().andEqualTo("supplierCode", baseInfo.getSupplierCode());
        seiMapper.updateByExampleSelective(extendInfo, e);
    }

    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        MbSupplierInfo si = loadById(id);
	    if (si == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.GET_SUPPLIER_INFO_NULL);
	    }
        String s = scSrv.queryRelatedUsefulOrg(si.getSupplierCode());
        if (StringUtils.isNotBlank(s)) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.SUPPLIER_IN_USE_DONT_DEL, s);
        }
        si.setIsDeleted(true);
        if (siMapper.updateByPrimaryKeySelective(si) == 0) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.SUPPLIER_DEL_EXPIRE);
        }
        ulSrv.delUserLoginBySupplierCode(si.getSupplierCode());
        Example e = new DefExample(MbSupplierExtendInfo.class);
        e.createCriteria().andEqualTo("supplierCode", si.getSupplierCode());
        MbSupplierExtendInfo sei = new MbSupplierExtendInfo();
        sei.setIsDeleted(true);
        seiMapper.updateByExampleSelective(sei, e);
    }

    List<MbSupplierInfo> loadAvailSuppliers() {
        Example e = new Example(MbSupplierInfo.class);
        e.createCriteria().andEqualTo("isDeleted", false)
                .andEqualTo("isFreeze", false);
        return siMapper.selectByExample(e);
    }

    int provideProductSupplierCount(ProductTypeEnum pt) {
        Example e = new DefExample(MbSupplierInfo.class);
        e.createCriteria()
                .andCondition("support_product &" + pt.getId());
        return siMapper.selectCountByExample(e);
    }

    List<MbSupplierInfo> provideProductSuppliers(ProductTypeEnum pt) {
        Example e = new DefExample(MbSupplierInfo.class);
        e.createCriteria()
                .andCondition("support_product &" + pt.getId());
        return siMapper.selectByExample(e);
    }

    public List<MbSupplierInfo> listUnFreeze() {
        Example e = new DefExample(MbSupplierInfo.class);
        e.createCriteria().andEqualTo("isFreeze", false);
        return siMapper.selectByExample(e);
    }

    public MbSupplierInfoVo get(String supplierCode) {
        MbSupplierInfo mbSupplierInfo = siMapper.get(supplierCode);
        if (mbSupplierInfo == null) {
            return null;
        }
        MbSupplierInfoVo mbSupplierInfoVo = JsonUtils.convert(mbSupplierInfo, MbSupplierInfoVo.class);
        mbSupplierInfoVo.setSupplierPhone(mbSupplierInfo.getSupplierPhone());
        mbSupplierInfoVo.setContactEmail(mbSupplierInfo.getContactEmail());
        Example example = new Example(MbSupplierExtendInfo.class);
        example.createCriteria().andEqualTo("supplierCode", supplierCode).andEqualTo("isDeleted", 0);
        MbSupplierExtendInfo mbSupplierExtendInfos = mbSupplierExtendInfoMapperl.selectOneByExample(example);
        if (mbSupplierExtendInfos != null) {
            mbSupplierInfoVo.setSettlementEmail(mbSupplierExtendInfos.getSettlementEmail());
            mbSupplierInfoVo.setAccountBank(mbSupplierExtendInfos.getAccountBank());
            mbSupplierInfoVo.setAccountCardNo(mbSupplierExtendInfos.getAccountCardNo());
            mbSupplierInfoVo.setInvoiceTitle(mbSupplierExtendInfos.getInvoiceTitle());
            mbSupplierInfoVo.setTaxpayerNumber(mbSupplierExtendInfos.getTaxpayerNumber());
        }
        mbSupplierInfoVo.setSupplierName(mbSupplierInfo.getSupplierName());
        return mbSupplierInfoVo;
    }

	public PageVo getSupplierList(QuerySupplierListRequest request) {
		//Example e = buildListExample(request.getNameOrId(), ProductTypeEnum.loadByName(request.getServiceType()), request.getIsFreeze());
        Example e = new DefExample(MbSupplierInfo.class);
        Example.Criteria c = e.createCriteria();
        if (StringUtils.isNotBlank(request.getNameOrId())) {
            c.andCondition(" (supplier_code like '" + request.getNameOrId()
                    + "' or supplier_name like '%" + request.getNameOrId()
                    + "%') ");
        }
        if (ProductTypeEnum.loadByName(request.getServiceType()) != null) {
            c.andCondition("support_product & " + ProductTypeEnum.loadByName(request.getServiceType()).getId());
        }
        if (request.getIsFreeze() != null) {
            c.andEqualTo("isFreeze", request.getIsFreeze());
        }
        IPage<MbSupplierInfo> pageInfo = PageContext.startPage(request.getPageNum(), request.getPageSize());
        siMapper.selectByExample(e);
        List<String> excludeType = Lists.newArrayList(ProductTypeEnum.i18n_flight.name(), ProductTypeEnum.other.name());
        List<SupplierListInfo> supplierListInfos = new ArrayList<>();
        pageInfo.getRecords().forEach(si ->{
                    SupplierListInfo sli = new SupplierListInfo();
					sli.setId(si.getId());
					sli.setSupplierName(si.getSupplierName());
					sli.setSupplierCode(si.getSupplierCode());
					sli.setContactName(si.getContactName());
					sli.setSupplierPhone(si.getSupplierPhone());
					sli.setIsFreeze(si.getIsFreeze());
					sli.setProducts(ProductTypeEnum.getProductList(si.getSupportProduct()).stream().filter(p -> !excludeType.contains(p)).collect(Collectors.toList()));
            supplierListInfos.add(sli);
        });
        return PageVo.builder().pageNum(pageInfo.getCurrent()).pageSize(pageInfo.getSize()).
                count(pageInfo.getTotal()).totalPage(pageInfo.getPages()).list(supplierListInfos).build();
	}

    public void validateParams(MbSupplierInfoVo si) {
        String licenceNo = si.getLicenceNo();
        String businessAddress = si.getBusinessAddress();
        if (StringUtils.isNotBlank(licenceNo)) {
            if (licenceNo.length() > 50) {
                throw new CorpBusinessException(OrganizationResponseCodeEnum.LICENCE_NO_LENGTH_ERROR);
            }
            if (StrUtils.havingChinese(licenceNo)) {
                throw new CorpBusinessException(OrganizationResponseCodeEnum.LICENCE_NO_ERROR);
            }
        }
        if (StringUtils.isNotBlank(businessAddress) && businessAddress.length() > 100) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.BUSINESS_ADDRESS_LENGTH_ERROR);
        }
    }

    @Data
    @AllArgsConstructor
    public static class SupplierInfo {
        private MbSupplierInfo basInfo;
        private MbSupplierExtendInfo extendInfo;
        private AtUserLoginVo adminInfo;
    }

    public List<MbSupplierInfoVo> querySupplierInfo(String nameOrCode, String excludeCorpId) {
        List<MbSupplierInfo> mbSupplierInfos = querySupplierListByNameOrCode(nameOrCode, excludeCorpId);

        return mbSupplierInfos.stream().map(info -> {
            MbSupplierInfoVo mbSupplierInfoVo = new MbSupplierInfoVo();
            mbSupplierInfoVo.setSupplierName(info.getSupplierName());
            mbSupplierInfoVo.setSupplierCode(info.getSupplierCode());
            return mbSupplierInfoVo;
        }).collect(Collectors.toList());
    }


    /**
     * 对客查询供应商信息
     *
     * @param supplierCode
     * @return
     */
    public GetSupplierInfoResponse soaGetSupplierInfo(String supplierCode) {

        // 查询基础信息
        Example example = new Example(MbSupplierInfo.class);
        example.createCriteria().andEqualTo("supplierCode", supplierCode)
            .andEqualTo("isFreeze", false)
            .andEqualTo("isDeleted", false);

        List<MbSupplierInfo> supplierInfoList = siMapper.selectByExample(example);
        log.info("soaQuerySupplierInfoList：{}", JsonUtils.toJsonString(supplierInfoList));

        GetSupplierInfoResponse result = new GetSupplierInfoResponse();
        if (CollectionUtils.isNotEmpty(supplierInfoList)) {
            // 理论上一个code只对应一个supplierInfo
            MbSupplierInfo info = supplierInfoList.get(0);
            result.setSupplierCode(info.getSupplierCode()).setSupplierName(info.getSupplierName());
        }
        return result;
    }
}
